# app/routes/main.py
# -*- coding: utf-8 -*-
'''
@File    :   main.py
@Time    :   2024/11/26
@Author  :   Wang Xi
@Version :   1.0
@Desc    :   主路由文件
'''

from fastapi import APIRouter, Depends, Form, Request, status
from fastapi.responses import HTMLResponse, RedirectResponse, JSONResponse
from fastapi.templating import Jinja2Templates
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from ..models.vim import vim
from ..models.vnf import Vnf
from .. import sessionLocal

router = APIRouter()

templates = Jinja2Templates(directory="app/templates")

def get_db():
    db = sessionLocal()
    try:
        yield db
    finally:
        db.close()


@router.get('/', response_class=HTMLResponse, name="main.index")
def index(request: Request, db: Session = Depends(get_db)):
    """
    获取所有已部署的VNF列表页面
    """
    vnfs = db.query(Vnf).all()
    return templates.TemplateResponse('index.html', {'request': request, 'vnfs': vnfs, 'vim': vim})

@router.get('/get_resources', response_class=JSONResponse, name="main.get_resources")
def get_resources(request: Request):
    return JSONResponse(
        content={"cpu_remain": vim.cpuRemain,
                 "ram_remain": vim.ramRemain,
                 "rom_remain": vim.romRemain},
        status_code=status.HTTP_200_OK
        )

@router.get('/get_vnfs', response_class=JSONResponse, name="main.get_vnfs")
def get_vnfs(request: Request, db: Session = Depends(get_db)):
    vnfs = db.query(Vnf).all()
    vnfList = [vnf.name for vnf in vnfs]
    return JSONResponse(
        content={"vnf_names": vnfList},
        status_code=status.HTTP_200_OK
    )

@router.post('/add_vnf', response_class=RedirectResponse, name="main.add_vnf")
def add_vnf(request: Request, 
            vnfname: str = Form(...), 
            vnftype: str = Form(...),
            vnfip: str = Form(...),
            vnfport: int = Form(...),
            vnfcpu: float = Form(...),
            vnfram: float = Form(...),
            vnfrom: float = Form(...),
            is_program_request: bool = Form(False), 
            db: Session = Depends(get_db)):
    """
    部署Vnf
    """
    try:
        if vnfcpu > vim.cpuRemain:
            if is_program_request:
                return JSONResponse(
                    content={"message": "Insufficient CPU resources"},
                    status_code=status.HTTP_400_BAD_REQUEST
                )
            else:
                return RedirectResponse(
                    str(request.url_for('main.index')) + '?error=Insufficient%20CPU%20resources',
                    status_code=status.HTTP_303_SEE_OTHER
                )

        if vnfram > vim.ramRemain:
            if is_program_request:
                return JSONResponse(
                    content={"message": "Insufficient RAM resources"},
                    status_code=status.HTTP_400_BAD_REQUEST
                )
            else:
                return RedirectResponse(
                    str(request.url_for('main.index')) + '?error=Insufficient%20RAM%20resources',
                    status_code=status.HTTP_303_SEE_OTHER
                )
            
        if vnfrom > vim.romRemain:
            if is_program_request:
                return JSONResponse(
                    content={"message": "Insufficient ROM resources"},
                    status_code=status.HTTP_400_BAD_REQUEST
                )
            else:
                return RedirectResponse(
                    str(request.url_for('main.index')) + '?error=Insufficient%20ROM%20resources',
                    status_code=status.HTTP_303_SEE_OTHER
                )

        new_vnf = Vnf(name=vnfname, type=vnftype, ip=vnfip, port=vnfport,
                      cpu=vnfcpu, ram=vnfram, rom=vnfrom)
        db.add(new_vnf)
        db.commit()

        vim.cpuRemain -= vnfcpu
        vim.ramRemain -= vnfram
        vim.romRemain -= vnfrom

        if is_program_request:
            return JSONResponse(
                content={"message": "VNF added successfully"},
                status_code=status.HTTP_201_CREATED
            )
        else:
            return RedirectResponse(request.url_for('main.index'), status_code=status.HTTP_303_SEE_OTHER)
    
    except IntegrityError:
        db.rollback()
        if is_program_request:
            return JSONResponse(
                content={"message": "Integrity error occurred"},
                status_code=status.HTTP_409_CONFLICT
            )
        else:
            return RedirectResponse(
                str(request.url_for('main.index')) + '?error=Integrity%20error%20occurred',
                status_code=status.HTTP_303_SEE_OTHER
            )


@router.post('/delete_vnf/{vnf_name}', response_class=RedirectResponse, name="main.delete_vnf")
def delete_vnf(request: Request, 
               vnf_name: str, 
               is_program_request: bool = Form(False),
               db: Session = Depends(get_db)):
    """
    移除Vnf
    """
    delete_vnf = db.query(Vnf).filter_by(name=vnf_name).first()
    if delete_vnf:
        db.delete(delete_vnf)
        db.commit()

        vim.cpuRemain += delete_vnf.cpu
        vim.ramRemain += delete_vnf.ram
        vim.romRemain += delete_vnf.rom

        if is_program_request:
            return JSONResponse(
                content={"message": "VNF deleted successfully"},
                status_code=status.HTTP_200_OK
            )
        else:
            return RedirectResponse(request.url_for('main.index'), status_code=status.HTTP_303_SEE_OTHER)
    else:
        if is_program_request:
            return JSONResponse(
                content={"message": "VNF not found"},
                status_code=status.HTTP_404_NOT_FOUND
            )
        else:
            return RedirectResponse(
                str(request.url_for('main.index')) + '?error=VNF%20not%20found',
                status_code=status.HTTP_303_SEE_OTHER
            )
